from numpy import (
    ndarray,  # 数组类型
    zeros,  # 创建全为零的数组
    sqrt,  # 平方根函数
    exp,  # 自然指数函数
    pi,  # 圆周率常量
)


def los_channel_error_model_in_sat2user_dist(
        error_model_config,  # 错误模型配置参数，包含距离误差的标准差
        satellite,  # 卫星对象，包含天线数量、用户距离、波长等属性
        users: list,  # 用户列表，每个用户表示一个通信用户
) -> ndarray:
    """
    该误差模型基于扰动后的卫星到用户距离估计来计算误差信道状态信息。

    参数:
    - error_model_config: 包含误差模型配置的对象，定义了距离误差的标准差
    - satellite: 卫星对象，包含天线增益、波长、用户距离等相关信息
    - users: 用户对象列表，表示通信系统中的多个用户

    返回:
    - ndarray: 包含误差信道状态信息的复数数组
    
    详细说明:
    - 该模型首先对卫星到用户的距离进行扰动，然后根据扰动后的距离来估算信道状态信息。
    - 最终返回的误差信道状态信息是基于每个用户的信号幅度和相位的变化。
    """

    # 初始化误差信道状态信息的数组，大小为（用户数量，卫星天线数量），数据类型为复数
    erroneous_channel_state_to_users = zeros((len(users), satellite.antenna_nr), dtype='complex')

    # 对于每个用户，计算其扰动后的信道状态信息
    for user in users:

        # 根据误差模型配置，对卫星到用户的距离进行扰动，使用正态分布随机生成扰动值
        satellite_to_user_distance_estimate = (
                satellite.distance_to_users[user.idx]  # 原始的卫星到用户的距离
                * satellite.rng.normal(loc=1, scale=error_model_config.distance_error_std)  # 基于正态分布的扰动
        )

        # 基于扰动后的距离估计值，计算信道的功率比
        power_ratio = (
                satellite.antenna_gain_linear  # 卫星的天线增益（线性值）
                * user.gain_linear  # 用户设备的增益（线性值）
                * (satellite.wavelength / (4 * pi * satellite_to_user_distance_estimate)) ** 2  # 距离衰减模型
        )
        # 根据功率比计算信号幅度的衰减
        amplitude_damping = sqrt(power_ratio)

        # 计算由于距离估计导致的相位偏移
        phase_shift = satellite_to_user_distance_estimate % satellite.wavelength * 2 * pi / satellite.wavelength

        # 计算误差信道状态，将幅度衰减和相位偏移应用于天线的方向矢量
        erroneous_channel_state_to_users[user.idx, :] = (
            amplitude_damping  # 幅度衰减
            * exp(1j * phase_shift)  # 相位偏移的复指数表示
            * satellite.steering_vectors_to_users[user.idx]  # 卫星天线到用户的方向矢量
        )

    # 返回包含误差的信道状态信息
    return erroneous_channel_state_to_users
